﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Abp.Extensions;
using IdentityModel;
using IdentityModel.Client;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Configuration;

namespace AVISOutBound.PCSite.ApiClient
{
    /// <summary>
    /// 调用api的客户端
    /// </summary>
    public class AvisApiClient
    {

        // 静态,连接复用
        private static readonly UnauthorizeHandler _clientHandler = new UnauthorizeHandler();
        private static readonly HttpClient _client = new HttpClient(_clientHandler);

        private static string _authority;
        private static string _accessToken;
        private static string _clientId;
        private static string _clientSecret;
        private static string _apiScope;

        //注入本次页面访问的httpcontext,便于注入流程处理
        public AvisApiClient(IHttpContextAccessor contextAccessor,IConfiguration configuration)
        {
            _authority = _authority??configuration["Authentication:Authority"];
            _clientId = _clientId??configuration["Authentication:ClientId"];
            _clientSecret = _clientSecret??configuration["Authentication:ClientSecret"];
            _apiScope = _apiScope??configuration["Authentication:ApiScope"];
            //使用带自动跳转的handler的httpclient
            _clientHandler.SetContext(contextAccessor.HttpContext);
            //初始化client_credentials的Access_token
            if (_accessToken.IsNullOrEmpty())
            {
                var disco = new DiscoveryClient(_authority).GetAsync(CancellationToken.None).Result;
                if (!disco.IsError)
                {
                    _accessToken = new TokenClient(disco.TokenEndpoint, _clientId, _clientSecret).RequestClientCredentialsAsync(_apiScope).Result.AccessToken;
                }
                //todo:日志记录,sso服务器状态异常
            }
        }

        /// <summary>
        /// 自动跳转的handler
        /// </summary>
        public class UnauthorizeHandler : DelegatingHandler
        {
            private HttpContext _context;

            public void SetContext(HttpContext context)
            {
                this._context = context;
            }

            public UnauthorizeHandler()
            {
                // 保证pipeline完整性
                InnerHandler = new HttpClientHandler();
            }

            // 在api调用中加入自动重定向的逻辑
            protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                HttpResponseMessage response;
                request.SetBearerToken(_accessToken);
                response = await base.SendAsync(request, cancellationToken);
                // clientcredencial token过期失效
                if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    var disco = await new DiscoveryClient(_authority).GetAsync(CancellationToken.None);
                    var tokenResponse = await new TokenClient(disco.TokenEndpoint, _clientId, _clientSecret).RequestClientCredentialsAsync(_apiScope);
                    _accessToken = tokenResponse.AccessToken;
                    request.SetBearerToken(_accessToken);
                    //隐式重连
                    response = await base.SendAsync(request, cancellationToken);
                }

                //如果ClientCredential权限不足,则使用用户登录后的权限
                if (response.StatusCode == HttpStatusCode.Forbidden)
                {
                    // 如果从未登录过,Challenge
                    if (!_context.User.Identity.IsAuthenticated)
                    {
                        await _context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
                        return response;
                    }
                    // 如果登陆过,直接获取AccessToken
                    _accessToken = await _context.GetTokenAsync("access_token");
                    request.SetBearerToken(_accessToken);
                    response = await base.SendAsync(request, cancellationToken);
                }
                return response;
            }
        }

        public async Task<string> GetIndexBanner()
        {
            try
            {
                var response = await _client.GetAsync("http://localhost:21021/api/services/app/Content/GetIndexBanner");
                return await response.Content.ReadAsStringAsync();
            }
            catch (Exception e)
            {
                return "接口调用失败,请检查服务状态";
            }
        }

        public async Task<string> GetLoginRequiredFunction()
        {
            try
            {
                var response = await _client.GetAsync("http://localhost:21021/api/services/app/Content/GetLoginRequiredFunction");
                return await response.Content.ReadAsStringAsync();
            }
            catch (Exception e)
            {
                return "接口调用失败,请检查服务状态";
            }
            
        }
    }

    
}
